package convert

import (
	"errors"
	"reflect"
)

// SliceToSlice 封装了对 slice 的转换。它接收 src 作为任意类型的切片，
// 并将其元素转换为 dst 指向的切片类型的元素。
func SliceToSlice(src any, dst any) error {
	// 验证 src 是否为切片
	srcVal := reflect.ValueOf(src)
	if srcVal.Kind() != reflect.Slice {
		return errors.New("src is not a slice")
	}

	// 验证 dst 是否是指向切片的指针
	dstVal := reflect.ValueOf(dst)
	if dstVal.Kind() != reflect.Ptr || dstVal.Elem().Kind() != reflect.Slice {
		return errors.New("dst is not a pointer to a slice")
	}

	// 获取指向 dst 切片的值
	dstSlice := dstVal.Elem()

	// 创建一个新的空切片，其类型与 dst 切片元素的类型相同
	newDst := reflect.MakeSlice(dstSlice.Type(), 0, srcVal.Len())

	// 迭代 src 切片的每一个元素
	for i := 0; i < srcVal.Len(); i++ {
		// 创建一个新的元素，其类型为 dst 切片元素的类型
		newElem := reflect.New(dstSlice.Type().Elem()).Elem()

		// 使用 AnyToAny 函数将 src 元素转换到新元素
		err := AnyToAny(srcVal.Index(i).Interface(), newElem.Addr().Interface())
		if err != nil {
			return err
		}

		// 将转换后的元素添加到新切片
		newDst = reflect.Append(newDst, newElem)
	}

	// 将新切片的值设置给 dst
	dstSlice.Set(newDst)

	return nil
}
